#ifndef GAMEENGINE_GRAPHICS_TEXTURE_TEXTURE_DEFS_H
#define GAMEENGINE_GRAPHICS_TEXTURE_TEXTURE_DEFS_H

#include <GameEngine/Graphics/graphics_settings.h>
#include <GameEngine/Graphics/openGL.h>


#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif

//=================================================================================


namespace Texture {
	//! Typedef to handle texture indexes
	typedef unsigned int TextureIndex;

	//! Typedef to handle texture sizes
	typedef unsigned int TextureSize;

	//! The internal format in which texture is specified
	enum TextureInternalFormat {
		//! Texture format cannot be found
		UndefinedInternalFormat = 0,
		//! Texture has one single color component
		OneInternalFormat = 1,
		//! Texture has two color components
		TwoInternalFormat = 2,
		//! Texture has three color components
		ThreeInternalFormat = 3,
		//! Texture has four color components
		FourInternalFormat = 4,
		//! Texture has one single alpha component
		AlphaInternalFormat = GL_ALPHA,
		//! Texture has one single alpha component stored on 4 bytes
		Alpha4InternalFormat = GL_ALPHA4,
		//! Texture has one single alpha component stored on 8 bytes
		Alpha8InternalFormat = GL_ALPHA8,
		//! Texture has one single alpha component stored on 12 bytes
		Alpha12InternalFormat = GL_ALPHA12,
		//! Texture has one single alpha component stored on 16 bytes
		Alpha16InternalFormat = GL_ALPHA16,
		//! Texture has one single alpha component stored using generic data compression
		CompressedAlphaInternalFormat = GL_COMPRESSED_ALPHA,
		//! Texture has luminance component stored using generic data compression
		CompressedLuminanceInternalFormat = GL_COMPRESSED_LUMINANCE,
		//! Texture has luminance and alpha components stored using generic data compression
		CompressedLuminanceAlphaInternalFormat = GL_COMPRESSED_LUMINANCE_ALPHA,
		//! Texture has intensity component stored using generic data compression
		CompressedIntensityInternalFormat = GL_COMPRESSED_INTENSITY,
		//! Texture has RGB components stored using generic data compression
		CompressedRGBInternalFormat = GL_COMPRESSED_RGB,
		//! Texture has RGBA components stored using generic data compression
		CompressedRGBAInternalFormat = GL_COMPRESSED_RGBA,
		//! Texture has a single depth component
		DepthComponentInternalFormat = GL_DEPTH_COMPONENT,
		//! Texture has a single depth component stored on 16 bytes
		DepthComponent16InternalFormat = GL_DEPTH_COMPONENT16,
		//! Texture has a single depth component stored on 24 bytes
		DepthComponent24InternalFormat = GL_DEPTH_COMPONENT24,
		//! Texture has a single depth component stored on 32 bytes
		DepthComponent32InternalFormat = GL_DEPTH_COMPONENT32,
		//! Texture has a single luminance component
		LuminanceInternalFormat = GL_LUMINANCE,
		//! Texture has a single luminance component stored on 4 bytes
		Luminance4InternalFormat = GL_LUMINANCE4,
		//! Texture has a single luminance component stored on 8 bytes
		Luminance8InternalFormat = GL_LUMINANCE8,
		//! Texture has a single luminance component stored on 12 bytes
		Luminance12InternalFormat = GL_LUMINANCE12,
		//! Texture has a single luminance component stored on 16 bytes
		Luminance16InternalFormat = GL_LUMINANCE16,
		//! Texture has luminance and alpha components
		LuminanceAlphaInternalFormat = GL_LUMINANCE_ALPHA,
		//! Texture has luminance and alpha components, respectively stored on 4 and 4 bytes
		Luminance4Alpha4InternalFormat = GL_LUMINANCE4_ALPHA4,
		//! Texture has luminance and alpha components, respectively stored on 6 and 2 bytes
		Luminance6Alpha2InternalFormat = GL_LUMINANCE6_ALPHA2,
		//! Texture has luminance and alpha components, respectively stored on 8 and 8 bytes
		Luminance8Alpha8InternalFormat = GL_LUMINANCE8_ALPHA8,
		//! Texture has luminance and alpha components, respectively stored on 12 and 4 bytes
		Luminance12Alpha4InternalFormat = GL_LUMINANCE12_ALPHA4,
		//! Texture has luminance and alpha components, respectively stored on 12 and 12 bytes
		Luminance12Alpha12InternalFormat = GL_LUMINANCE12_ALPHA12,
		//! Texture has luminance and alpha components, respectively stored on 16 and 16 bytes
		Luminance16Alpha16InternalFormat = GL_LUMINANCE16_ALPHA16,
		//! Texture has a single intensity component
		IntensityInternalFormat = GL_INTENSITY,
		//! Texture has a single intensity component stored on 4 bytes
		Intensity4InternalFormat = GL_INTENSITY4,
		//! Texture has a single intensity component stored on 8 bytes
		Intensity8InternalFormat = GL_INTENSITY8,
		//! Texture has a single intensity component stored on 12 bytes
		Intensity12InternalFormat = GL_INTENSITY12,
		//! Texture has a single intensity component stored on 16 bytes
		Intensity16InternalFormat = GL_INTENSITY16,
		//! Texture has R, G and B components, respectively stored on 3, 3 and 2 bytes
		R3G3B2InternalFormat = GL_R3_G3_B2,
		//! Texture has RGB components
		RGBInternalFormat = GL_RGB,
		//! Texture has RGB components stored on 4 bytes
		RGB4InternalFormat = GL_RGB4,
		//! Texture has RGB components stored on 5 bytes
		RGB5InternalFormat = GL_RGB5,
		//! Texture has RGB components stored on 8 bytes
		RGB8InternalFormat = GL_RGB8,
		//! Texture has RGB components stored on 10 bytes
		RGB10InternalFormat = GL_RGB10,
		//! Texture has RGB components stored on 12 bytes
		RGB12InternalFormat = GL_RGB12,
		//! Texture has RGB components stored on 16 bytes
		RGB16InternalFormat = GL_RGB16,
		//! Texture has RGBA components
		RGBAInternalFormat = GL_RGBA,
		//! Texture has RGBA components stored on 2 bytes
		RGBA2InternalFormat = GL_RGBA2,
		//! Texture has RGBA components stored on 4 bytes
		RGBA4InternalFormat = GL_RGBA4,
		//! Texture has RGBA components, respectively stored on 5 bytes for the RGB part and 1 byte for the A part
		RGB5A1InternalFormat = GL_RGB5_A1,
		//! Texture has RGBA components stored on 8 bytes
		RGBA8InternalFormat = GL_RGBA8,
		//! Texture has RGBA components, respectively stored on 10 bytes for the RGB part and 2 bytes for the A part
		RGB10A2InternalFormat = GL_RGB10_A2,
		//! Texture has RGBA components stored on 12 bytes
		RGBA12InternalFormat = GL_RGBA12,
		//! Texture has RGBA components stored on 16 bytes
		RGBA16InternalFormat = GL_RGBA16,
		//! Texture has a single luminance component, defined in the sRGB color space
		SLuminanceInternalFormat = GL_SLUMINANCE,
		//! Texture has a single luminance component, defined in the sRGB color space and stored on 8 bytes
		SLuminance8InternalFormat = GL_SLUMINANCE8,
		//! Texture has luminance and alpha components, defined in the sRGB color space
		SLuminanceAlphaInternalFormat = GL_SLUMINANCE_ALPHA,
		//! Texture has luminance and alpha components, defined in the sRGB color space and respectively stored on 8 and 8 bytes
		SLuminance8Alpha8InternalFormat = GL_SLUMINANCE8_ALPHA8,
		//! Texture has RGB components, defined in the sRGB color space
		SRGBInternalFormat = GL_SRGB,
		//! Texture has RGB components, defined in the sRGB color space and stored on 8 bytes
		SRGB8InternalFormat = GL_SRGB8,
		//! Texture has RGBA components, defined in the sRGB color space
		SRGBAlphaInternalFormat = GL_SRGB_ALPHA,
		//! Texture has RGBA components, defined in the sRGB color space and respectively stored on 8 bytes for the RGB part and 8 bytes for the A part
		SRGB8Alpha8InternalFormat = GL_SRGB8_ALPHA8
	};

	//! The way texture is interacts with the previous colors of the scene
	enum ApplicationMode {
		//! The texture application mode cannot be defined
		UndefinedApplicationMode = 0,
		//! The texture color is added to the underlying color
		/*!
		 *  Color function is: new_color = texture_color + previous_color
		 */
		AddMode = GL_ADD,
		//! The texture color modulates the underlying color
		/*!
		 *  Color function is: new_color = texture_color * previous_color
		 */
		ModulateMode = GL_MODULATE,
		//! The texture color is overlaid on the underlying color
		/*!
		 *  Color function is: new_color = previous_color * ( 1 - texture_color_alpha ) + texture_color * texture_color_alpha
		 */
		DecalMode = GL_DECAL,
		//! The texture color is blended with the underlying color
		/*!
		 *  Color function is: new_color = previous_color * ( 1 - texture_color ) + environment_color * texture_color
		 */
		BlendMode = GL_BLEND,
		//! The texture color is used
		/*!
		 *  Color function is: new_color = texture_color
		 */
		ReplaceMode = GL_REPLACE
	};

	//! The texture wrap mode when texture coordinates are out of range [0,1]
	enum WrapMode {
		//! Texture coordinates are clamped to interval [0,1]
		ClampMode = GL_CLAMP,
		//! Texture coordinates are clamped to the border
		/*!
		 *  Texture coordinates are clamped to interval [-1/(2*N),1+1/(2*N)], where N is the size of the texture
		 */
		ClampToBorderMode = GL_CLAMP_TO_BORDER,
		//! Texture coordinates are clamped to the edge
		/*!
		 *  Texture coordinates are clamped to interval [1/(2*N),1-1/(2*N)], where N is the size of the texture
		 */
		ClampToEdgeMode = GL_CLAMP_TO_EDGE,
		//! Texture coordinates are repeated over the texture space as if viewed in a mirror
		/*!
		 *  This removes the integer part from out-of-range texture coordinates. If integer part was even, this
		 *  mode returns the rest; if integer part was odd, this mode returns one minus the rest.
		 */
		MirroredRepeatMode = GL_MIRRORED_REPEAT,
		//! Texture coordinates are repeated over the texture space
		/*!
		 *  This removes the integer part from out-of-range texture coordinates
		 */
		RepeatMode = GL_REPEAT
	};

	//! Filter used when texture is zoomed in
	enum MagnifyingFilter {
		//! Magnifying filter cannot be defined
		UndefinedMagnifyingFilter = 0,
		//! Nearest texel is applied
		NearestMagFilter = GL_NEAREST,
		//! The color of neighbour texels is interpolated
		LinearMagFilter = GL_LINEAR
	};

	//! Filter used when texture is zoomed out
	enum MinifyingFilter {
		//! Minifying filter cannot be defined
		UndefinedMinifyingFilter = 0,
		//! Nearest texel is applied
		NearestMinFilter = GL_NEAREST,
		//! The color of neighbour texels is interpolated
		LinearMinFilter = GL_LINEAR,
		//! The nearest mipmap is selected; within this mipmap, the nearest texel is applied
		NearestMipmapNearestMinFilter = GL_NEAREST_MIPMAP_NEAREST,
		//! The nearest mipmap is selected; within this mipmap, the color of neighbour texels is interpolated
		LinearMipmapNearestMinFilter = GL_LINEAR_MIPMAP_NEAREST,
		//! The two nearest mipmaps are interpolated; within this interpolated mipmap, the nearest texel is applied
		NearestMipmapLinearMinFilter = GL_NEAREST_MIPMAP_NEAREST,
		//! The two nearest mipmaps are interpolated; within this interpolated mipmap, the color of neighbour texels is interpolated
		LinearMipmapLinearMinFilter = GL_LINEAR_MIPMAP_NEAREST
	};

	//! Determine the use of mipmaps (or not) in the texture
	enum MipmapMode {
		//! The use of mipmaps with the texture in unknown
		UndefinedMipmapMode = -1,
		//! No mipmaps are used with the texture
		NoMipmapMode = GL_FALSE,
		//! Mipmaps are used with the texture
		UseMipmapMode = GL_TRUE
	};
} // namespace Texture

#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif

#endif
